package com.googlecode.tidej.client.editor;

import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window.Navigator;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.googlecode.tidej.client.Console;
import com.googlecode.tidej.client.TidejController;
import com.googlecode.tidej.client.codemirror.CodeMirror;
import com.googlecode.tidej.client.codemirror.CodeMirror.LocalVar;
import com.googlecode.tidej.shared.model.Library;
import com.googlecode.tidej.shared.model.Operation;
import com.googlecode.tidej.shared.model.Parameter;
import com.googlecode.tidej.shared.model.Property;
import com.googlecode.tidej.shared.model.Type;

public class CodeEditor extends Composite {
  FlowPanel editorPanel = new FlowPanel();
  Operation operation;
  CodeMirror codeMirror;
  SuggestList suggestList;
  TidejController controller;
 
  static int cnt = 0;
  int nr = ++cnt;
  
  public CodeEditor(TidejController controller, final SuggestList suggestList) {
    this.controller = controller;
    this.suggestList = suggestList;
 //   editorPanel.setSize("100%", "100%");
   // panel.add(textArea);
    Style style = editorPanel.getElement().getStyle();
       
    style.setBorderWidth(0, Unit.PX);
   // style.setProperty("fontFamily", "monospace");
    style.setProperty("boxSizing", "border-box");
    style.setProperty("WebkitBoxSizing", "border-box");
    style.setProperty("MozBoxSizing", "border-box");
 //   style.setProperty("overflow", "auto");
   // style.setProperty("resize", "none"); 
    
//  mainPanel.addEast(suggestList, 200);
   
  //  mainPanel.add(editorPanel);
    initWidget(editorPanel); // mainPanel);
    
    new Timer() {
      @Override
      public void run() {
        if (codeMirror != null) {
          suggestList.update();
        }
      }
    }.scheduleRepeating(1000);
  }

  public void setOperation(Operation operation) {
    this.operation = operation;
    editorPanel.getElement().setInnerText("");
    
    CodeMirror.LocalVar lv = null;
    Type owner = operation.getOwner();
    if (owner != null && owner.getName().indexOf('(') == -1 && owner.getName().indexOf('<') == -1) {
      lv = LocalVar.create("this", owner, owner, null);
    }
    for (Parameter p: operation.getParameters()) {
      lv = CodeMirror.LocalVar.create(p.getName(), p, p.getType(), lv);
    }
    for (Library lib : controller.getModel().getLibraries()) {
      Type globals = lib.getGlobals();
      if (globals != null) {
        for (Operation op: globals.getOwnOperations()) {
          lv = CodeMirror.LocalVar.create(op.getName(), op, op.getType(), lv);
        } 
        for (Property p: globals.getOwnProperties()) {
          lv = CodeMirror.LocalVar.create(p.getName(), p, p.getType(), lv);
        } 
      } 
      for (Type type: lib.getTypes()) {
        if (type.getMetaType().getOwnOperations().size () > 0 || type.getMetaType().getOwnProperties().size() > 0) {
          lv = CodeMirror.LocalVar.create(type.getName(), type, type.getMetaType(), lv);
        }
      }
    }
    Console.log("Variables: " + CodeMirror.LocalVar.toString(lv));
    
    CodeMirror.Configuration config = CodeMirror.Configuration.create();
    CodeMirror.ParserConfig pc = CodeMirror.ParserConfig.create("javascript");
    pc.setLocalVariables(lv);
    config.setMode(pc);
    
    //config.setLineNumbers(true);
    codeMirror = CodeMirror.create(editorPanel.getElement(), config);
    StringBuilder body = new StringBuilder(operation.getBody() == null ? "" : operation.getBody());
    if (Navigator.getUserAgent().indexOf("iPad") != -1) {
      for (int i = 0; i < 10; i++) {
        body.append("\n\n\n\n\n\n\n\n\n\n");
      }
    } else {
      body.append("\n\n");
    }
    
    codeMirror.setValue(body.toString());
    suggestList.setEditor(this);
    codeMirror.refresh();
  }

  
  public boolean checkModifications() {
    boolean result = false;
    if (codeMirror == null) {
      return false;
    }
    String text = codeMirror.getValue();
    int cut = text.length();
    while(cut > 0 && text.charAt(cut - 1) == '\n') {
      cut--;
    }
    text = text.substring(0, cut);
    if (operation != null && !text.equals(operation.getBody())) {
      operation.setBody(text);
      result = true;
    } 
    return result;
  }
  
}
